package com.culturalCenter.dataCenter.schedule.training;

import cn.hutool.core.date.DateUtil;
import com.culturalCenter.dataCenter.Utils.RedisUtil;
import com.culturalCenter.dataCenter.entity.training.*;
import com.culturalCenter.dataCenter.enums.PlatformEnum;
import com.culturalCenter.dataCenter.mapper.training.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 定时任务_培训_统计
 *
 * @author colors
 * @date 2021/3/16 14:41
 */
@Component
@Slf4j
@Async("dataThreadExecutor")
public class TrainingDataStatistics {

    @Resource
    private TrainingInfoCountMapper trainingInfoCountMapper;
    @Resource
    private TrainingMonthCountMapper trainingMonthCountMapper;
    @Resource
    private TrainingTimeIntervalMapper trainingTimeIntervalMapper;
    @Resource
    private TrainingAttendanceMapper trainingAttendanceMapper;
    @Resource
    private TrainingClientCountMapper trainingClientCountMapper;
    @Resource
    private TrainingCommentCountMapper trainingCommentCountMapper;
    @Resource
    private TrainingAudienceCountMapper trainingAudienceCountMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redisson;

    /**
     * for test
     */
    // @PostConstruct
    public void initLock() {
        for (int i = 1; i <= 7; i++) {
            redisUtil.del("trainingStatistics_lock" + i);
        }
    }

    /**
     * 培训本月新增统计（cdc_training_month_count）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void countTrainCurrentMonth() {
        String lockKey = "trainingStatistics_lock1";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("******************培训本月新增统计开始**********************");

            List<TrainingMonthCount> dataList = new ArrayList<>();
            List<String> branchIds = trainingMonthCountMapper.getBranchIds();
            branchIds.forEach(branchId -> {
                for (Date beginDay = DateUtil.beginOfMonth(DateUtil.date()); beginDay.before(DateUtil.beginOfDay(DateUtil.tomorrow())); beginDay = DateUtil.offsetDay(beginDay, 1)) {
                    TrainingMonthCount countData = trainingMonthCountMapper.selectCountByBranchIdAndDay(beginDay, branchId);
                    countData.setId(UUID.randomUUID().toString());
                    countData.setBranchId(branchId);
                    countData.setTrainingBeginTime(beginDay);
                    dataList.add(countData);
                }
            });
            trainingMonthCountMapper.clearTable();
            trainingMonthCountMapper.insertBatch(dataList);

            log.info("************************培训本月新增统计完毕***********************");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 培训基础信息统计（cdc_training_info_count）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void countTrainingInfo() {
        String lockKey = "trainingStatistics_lock2";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("***********************培训统计表开始统计****************");

            List<TrainingInfoCount> trainingInfoCountList = trainingInfoCountMapper.countData();
            if (CollectionUtils.isNotEmpty(trainingInfoCountList)) {
                for (TrainingInfoCount trainingInfoCount : trainingInfoCountList) {
                    String id = UUID.randomUUID().toString();
                    trainingInfoCount.setId(id);
                }
                trainingInfoCountMapper.insertBatch(trainingInfoCountList);
            }

            log.info("***************************培训统计表统计完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 培训报名时段统计（cdc_training_time_interval）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void countSignUpInterval() {
        String lockKey = "trainingStatistics_lock3";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("***********************开始统计所有分馆培训报名时段表****************");

            List<TrainingTimeInterval> intervalList = trainingTimeIntervalMapper.countData();
            if (CollectionUtils.isNotEmpty(intervalList)) {
                for (TrainingTimeInterval trainingTimeInterval : intervalList) {
                    String id = UUID.randomUUID().toString();
                    trainingTimeInterval.setId(id);
                }
                trainingTimeIntervalMapper.clearTable();
                trainingTimeIntervalMapper.insertBatch(intervalList);
            }

            log.info("***************************所有分馆培训报名时段表统计完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 统计考勤人数（cdc_training_attendance）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void countAttendance() {
        String lockKey = "trainingStatistics_lock4";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            // 签到人数
            log.info("*********************开始更新签到人数**************************");
            List<TrainingAttendance> signInNumList = trainingAttendanceMapper.countSignInNum();
            if (CollectionUtils.isNotEmpty(signInNumList)) {
                for (TrainingAttendance trainingAttendance : signInNumList) {
                    trainingAttendance.setId(UUID.randomUUID().toString());
                }
                trainingAttendanceMapper.insertBatch(signInNumList);
            }

            // 迟到人数
            log.info("*********************开始更新迟到人数**************************");
            List<TrainingAttendance> lateNumList = trainingAttendanceMapper.countLateNum();
            if (CollectionUtils.isNotEmpty(lateNumList)) {
                for (TrainingAttendance trainingAttendance : lateNumList) {
                    trainingAttendance.setId(UUID.randomUUID().toString());
                }
                trainingAttendanceMapper.insertLateNum(lateNumList);
            }

            // 请假人数
            log.info("*********************开始更新请假人数**************************");
            List<TrainingAttendance> leaveNumList = trainingAttendanceMapper.countLeaveNum();
            if (CollectionUtils.isNotEmpty(leaveNumList)) {
                for (TrainingAttendance trainingAttendance : leaveNumList) {
                    trainingAttendance.setId(UUID.randomUUID().toString());
                }
                trainingAttendanceMapper.insertLeaveNum(leaveNumList);
            }

            // 早退人数
            log.info("*********************开始更新早退人数**************************");
            List<TrainingAttendance> earlyNumList = trainingAttendanceMapper.countEarlyNum();
            if (CollectionUtils.isNotEmpty(earlyNumList)) {
                for (TrainingAttendance trainingAttendance : earlyNumList) {
                    trainingAttendance.setId(UUID.randomUUID().toString());
                }
                trainingAttendanceMapper.insertEarlyNum(earlyNumList);
            }

            // 缺席人数
            log.info("*********************开始更新缺席人数**************************");
            List<TrainingAttendance> absentNumList = trainingAttendanceMapper.countAbsentNum();
            if (CollectionUtils.isNotEmpty(absentNumList)) {
                for (TrainingAttendance trainingAttendance : absentNumList) {
                    trainingAttendance.setId(UUID.randomUUID().toString());
                }
                trainingAttendanceMapper.insertAbsentNum(absentNumList);
            }

            // 全勤率
            log.info("*********************开始更新全勤率**************************");
            List<TrainingAttendance> attendanceRateList = trainingAttendanceMapper.countAttendanceRate();
            if (CollectionUtils.isNotEmpty(attendanceRateList)) {
                for (TrainingAttendance trainingAttendance : attendanceRateList) {
                    trainingAttendance.setId(UUID.randomUUID().toString());
                }
                trainingAttendanceMapper.insertAttendanceRate(attendanceRateList);
            }

            log.info("***************************cdc_training_attendance统计完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 统计报名平台（cdc_training_client_count）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void platformTypeCount() {
        String lockKey = "trainingStatistics_lock5";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("***************************开始统计报名平台***********************");

            List<TrainingClientCount> clientCounts = trainingClientCountMapper.countData();
            if (CollectionUtils.isNotEmpty(clientCounts)) {
                for (TrainingClientCount clientCount : clientCounts) {
                    clientCount.setId(UUID.randomUUID().toString());
                    if (clientCount.getPlatformType() != null) {
                        clientCount.setPlatformType(PlatformEnum.platform(Integer.valueOf(clientCount.getPlatformType())));
                    }
                }
                trainingClientCountMapper.clearTable();
                trainingClientCountMapper.insertBatch(clientCounts);

                log.info("***************************报名平台统计完毕");
            }
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 统计评论星数（cdc_training_comment_count）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void commentCount() {
        String lockKey = "trainingStatistics_lock6";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_comment_count开始统计");

            List<TrainingCommentCount> commentCounts = trainingCommentCountMapper.countData();
            if (CollectionUtils.isNotEmpty(commentCounts)) {
                for (TrainingCommentCount commentCount : commentCounts) {
                    commentCount.setId(UUID.randomUUID().toString());
                }
            }
            trainingCommentCountMapper.insertBatch(commentCounts);

            log.info("***************************cdc_training_comment_count统计完毕");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 统计报名中男女比例（cdc_training_audience_count）
     */
//    @Scheduled(cron = "${cron.trainingStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void genderAnalysis() {
        String lockKey = "trainingStatistics_lock7";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("cdc_training_audience_count开始统计");

            List<TrainingAudienceCount> genderAnalysis = trainingAudienceCountMapper.countGender();
            if (CollectionUtils.isNotEmpty(genderAnalysis)) {
                for (TrainingAudienceCount analysis : genderAnalysis) {
                    analysis.setId(UUID.randomUUID().toString());
                }
                trainingAudienceCountMapper.insertBatch(genderAnalysis);

                log.info("***************************cdc_training_audience_count统计完毕");
            }
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

}
